package com.ssyx.handler;

import com.alibaba.fastjson.JSONObject;
import com.ssyx.auth.AuthThreadLocal;
import com.ssyx.constant.GlobalConstant;
import com.ssyx.constant.RedisConstant;
import com.ssyx.exception.SsyxException;
import com.ssyx.result.ResultCodeEnum;
import com.ssyx.utils.JwtHelper;
import com.ssyx.vo.user.UserLoginVo;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;

@Slf4j
@Component
public class LoginInterceptor implements HandlerInterceptor {
	private final RedisTemplate<String, Object> redisTemplate;
	
	public LoginInterceptor(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}
	
	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) {
		//判断当前拦截到的是Controller的方法还是其他资源
		if (!(handler instanceof HandlerMethod)) {
			//当前拦截到的不是动态方法，直接放行
			return true;
		}
		String token = request.getHeader("token");
		if (token.equals(GlobalConstant.VALIDATE)) {
			return true;
		}
		log.info("token令牌：{}", token);
		if (StringUtils.isEmpty(token)) {
			log.error("令牌不存在");
			response.setStatus(401);
			throw new SsyxException(ResultCodeEnum.LOGIN_AUTH);
		}
		try {
			//校验令牌
			Long id = JwtHelper.getId(token);
			String name = JwtHelper.getName(token);
			log.info("token登录用户：id:{},name:{}", id, name);
			String redisToken = null;
			UserLoginVo userLoginVo = null;
			if (id != null) {
				Object adminInfo = redisTemplate.opsForValue().get(RedisConstant.ADMIN_KEY_PREFIX + id);
				if (adminInfo != null) {
					redisToken = adminInfo.toString();
				} else {
					redisToken = (String) redisTemplate.opsForValue().get(RedisConstant.USER_KEY_PREFIX + id);
					userLoginVo =
							JSONObject.parseObject((String) redisTemplate.opsForValue().get(RedisConstant.USER_LOGIN_KEY_PREFIX +
									id), UserLoginVo.class);
				}
			}
			if (StringUtils.isEmpty(redisToken)) {
				response.setStatus(401);
				log.error("令牌已过期");
				throw new SsyxException(ResultCodeEnum.EXPIRED_TOKEN);
			}
			if (!token.equals(redisToken)) {
				response.setStatus(401);
				log.error("令牌已过期");
				throw new SsyxException(ResultCodeEnum.EXPIRED_TOKEN);
			}
			Map<String, Object> adminInfo =
					(Map<String, Object>) redisTemplate.opsForValue().get(RedisConstant.ADMIN_LOGIN_KEY_PREFIX +
							AuthThreadLocal.getId());
			if (adminInfo != null) {
				AuthThreadLocal.setWare((Long) adminInfo.get("wareId"));
			}
			if (userLoginVo != null) {
				log.info("用户登录信息：{}", userLoginVo);
				AuthThreadLocal.setUserLoginVo(userLoginVo);
				AuthThreadLocal.setWare(userLoginVo.getWareId());
			}
			Long redisId = JwtHelper.getId(redisToken);
			String redisName = JwtHelper.getName(redisToken);
			log.info("redis登录用户：redisId:{},redisName:{}", redisId, redisName);
			if (!id.equals(redisId) || !name.equals(redisName)) {
				log.error("令牌已过期");
				response.setStatus(401);
				throw new SsyxException(ResultCodeEnum.EXPIRED_TOKEN);
			}
			AuthThreadLocal.setId(id);
			// 通过，放行
			return true;
		} catch (Exception e) {
			response.setStatus(401);
			throw new RuntimeException(e);
		}
	}
	
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
	                            Exception ex) {
		AuthThreadLocal.removeId();
		AuthThreadLocal.removeWare();
		AuthThreadLocal.removeUserLoginVo();
	}
}
